package com.share.commons.base.dao;

import java.io.Serializable;
import java.sql.SQLException;
import java.util.LinkedHashMap;
import java.util.List;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.orm.hibernate3.HibernateCallback;

import com.share.commons.base.query.BaseQuery;
import com.share.commons.base.query.PageModel;
import com.share.commons.base.query.QueryUtil;

/**
 * 说明：基础DAO实现类
 * 该类是个抽象类，并继承了HibernateTemplateSupport获得hibernateTemplate
 * 使用hibernateTemplate来操作数据库
 * <br/>作者： 杨浩泉
 * <br/>日期： 2010-2-24
 */
public class BaseDaoSupport<T> extends HibernateTemplateSupport<T> implements BaseDao<T> {
	
	@SuppressWarnings("unchecked")
	@Override
	public T getById(Class<T> entityClass, Serializable id)
			throws RuntimeException {
		return (T) getHiberanteTemplate().get(entityClass, id) ;
	}

	@Override
	public void insertOrUpdate(T entity) throws RuntimeException {
		getHiberanteTemplate().saveOrUpdate(entity) ;
	}

	@SuppressWarnings("unchecked")
	@Override
	public T loadById(Class<T> entityClass, Serializable id)
			throws RuntimeException {
		return (T) getHiberanteTemplate().load(entityClass, id) ;
	}

	@Override
	public void saveObject(T entity) throws RuntimeException {
		getHiberanteTemplate().save(entity) ;
	}
	
	@Override
	public Serializable saveObjectRet(T entity) throws RuntimeException {
		return getHiberanteTemplate().save(entity) ;
	}

	@Override
	public void updateObject(T entity) throws RuntimeException {
		getHiberanteTemplate().update(entity) ;
	}
	
	@Override
	public void deleteObject(Class<T> entityClass, Serializable id)
	throws RuntimeException {
		getHiberanteTemplate().delete(loadById(entityClass,id)) ;
	}
	
	@Override
	public void deleteObject(T entity) throws RuntimeException {
		getHiberanteTemplate().delete(entity) ;
	}

	@Override
	public void deleteAllObject(final Class<T> entityName, final Object[] ids)
			throws RuntimeException {
		this.getHiberanteTemplate().execute(new HibernateCallback() {
			
			@Override
			public Object doInHibernate(Session session) throws HibernateException,
					SQLException {
				if(ids.length > 0) {
					for(int i=0; i<ids.length; i++) {
						session.delete(loadById(entityName,ids[i].toString())) ;
						if(ids.length%20==0) {
							session.flush() ;
							session.clear() ;
						}
					}
				}
				return null;
			}
		}) ;
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public List<Object> findByProperty(final String property, final String clazz, final String whereHQL,final Object[] param) throws RuntimeException {
		
		return (List<Object>) this.getHiberanteTemplate().execute(new HibernateCallback() {
			@Override
			public Object doInHibernate(Session session) throws HibernateException, SQLException {
				
				String hql = "select " + buildProperty(property) + " from " + clazz + buildWhereHQL(whereHQL);
				Query query = session.createQuery(hql) ;
				
				setQueryParams(query, param) ;
				return query.list() ;
			}
		}) ;
	}
	
	/**
	 * 不根据条件查询
	 */
	@SuppressWarnings("unchecked")
	@Override
	public List<Object> findByProperty(final String property, final String clazz) throws RuntimeException {
		
		return (List<Object>) this.getHiberanteTemplate().execute(new HibernateCallback() {
			@Override
			public Object doInHibernate(Session session) throws HibernateException, SQLException {
				
				String hql = "select " + buildProperty(property) + " from " + clazz ;
				Query query = session.createQuery(hql) ;
				
				return query.list() ;
			}
		}) ;
	}

	@SuppressWarnings("unchecked")
	@Override
	public T findSingleEntity(final String hql,final String whereHQL,final List<Object> param) throws RuntimeException {
		
		return (T) getHiberanteTemplate().execute(new HibernateCallback() {
			@Override
			public Object doInHibernate(Session session) throws HibernateException,
					SQLException {
				
				Query query = session.createQuery(hql + buildWhereHQL(whereHQL)) ;
				setQueryParams(query, param) ;
				
				return query.uniqueResult() ;
			}
		}) ;
	}
	
	public Object executeHQL(final String hql,final String setHQL,final String whereHQL,final Object[] param) throws RuntimeException {
		
		return this.getHiberanteTemplate().execute(new HibernateCallback() {
			
			@Override
			public Object doInHibernate(Session session) throws HibernateException,
					SQLException {
				
				System.out.println(hql + buildSetHQL(setHQL) + buildWhereHQL(whereHQL));
				
				Query query = session.createQuery(hql + buildSetHQL(setHQL) + buildWhereHQL(whereHQL)) ;
				
				setQueryParams(query, param) ;
				
				return query.executeUpdate();
			}
		}) ;
	}
	
	@SuppressWarnings("unchecked")
	public T find(final String hql,final String whereHQL,final List<Object> param,final LinkedHashMap<String , String> orderby) throws RuntimeException {
		
		return (T) this.getHiberanteTemplate().execute(new HibernateCallback() {
			@Override
			public Object doInHibernate(Session session) throws HibernateException,
					SQLException {
				System.out.println(hql + buildWhereHQL(whereHQL) + buildOrderBy(orderby));
				Query query = session.createQuery(hql + buildWhereHQL(whereHQL) + buildOrderBy(orderby)) ;
				
				setQueryParams(query, param) ;
				
				return query.list();
			}
		}) ;
	}
	/**
	 * 根据条件查询，但不排序
	 */
	public T find(final String hql,final String whereHQL,final List<Object> param) throws RuntimeException {
		return this.find(hql, whereHQL, param, null) ;
	}
	/**
	 * 不根据条件查询，但排序
	 */
	public T find(final String hql,final LinkedHashMap<String , String> orderby) throws RuntimeException {
		return this.find(hql, null, null, orderby) ;
	}
	/**
	 * 不排序和条件查询
	 */
	public T find(final String hql) throws RuntimeException {
		return this.find(hql, null, null, null) ;
	}

	
	@SuppressWarnings("unchecked")
	@Override
	public PageModel<T> getScrollData(final String hql,final String whereHQL, final List<Object> param, final int firstResult,
			final int maxResult,final LinkedHashMap<String , String> orderby) throws RuntimeException {
		
		return (PageModel)getHiberanteTemplate().execute(new HibernateCallback() {
			
			@Override
			public Object doInHibernate(Session session) throws HibernateException,
					SQLException {
				PageModel<T> pm = null ;
				List resultList = null ;
				
				System.out.println("打印拼装语句【"+ hql + buildWhereHQL(whereHQL) + buildOrderBy(orderby) + "】");
			
				Query query = session.createQuery(hql + buildWhereHQL(whereHQL) + buildOrderBy(orderby)) ;
				
				setQueryParams(query, param) ;
				
				if(firstResult!=-1 && maxResult!=-1) query.setFirstResult(firstResult).setMaxResults(maxResult);
				
				resultList = query.list() ;
				
				//统计总记录数
				if(null != resultList && resultList.size()>0) {
					pm = new PageModel<T>() ;
					pm.setResultList(resultList) ;
					pm.setTotalRecord(QueryUtil.getListCount(session, hql + buildWhereHQL(whereHQL),param).intValue()) ;
				}
 				
				return pm;
			}
		}) ;
	}
	/**
	 * 根据条件查询并分页，但不排序
	 */
	public PageModel<T> getScrollData(String hql,final String whereHQL, List<Object> param, int firstResult,
			int maxResult) throws RuntimeException {
		return this.getScrollData(hql, whereHQL, param, firstResult, maxResult, null) ;
	}
	/**
	 * 排序并分页，但不根据条件查询
	 */
	public PageModel<T> getScrollData(String hql, int firstResult,int maxResult,final LinkedHashMap<String , String> orderby) throws RuntimeException {
		return this.getScrollData(hql, null, null, firstResult, maxResult, orderby) ;
	}
	/**
	 * 不排序和条件查询，进行分页
	 */
	public PageModel<T> getScrollData(String hql,int firstResult,int maxResult) throws RuntimeException {
		return this.getScrollData(hql, null, null, firstResult, maxResult, null) ;
	}
	

	/**
	 * 获得查询条件语句
	 * @param whereHQL
	 * @return
	 */
	protected static String buildWhereHQL(String whereHQL) {
		return (null == whereHQL || "".equals(whereHQL.trim()) ? "" :BaseQuery.WHERE+whereHQL) ;
	}
	
	/**
	 * 获得修改条件语句
	 * @param buildSetHQL
	 * @return
	 */
	protected static String buildSetHQL(String setHQL) {
		return (null == setHQL || "".equals(""+setHQL.trim()) ? "" : BaseQuery.SET + setHQL) ;
	}
	
	/**
	 * 设置参数值
	 * @param query
	 * @param param<List>
	 */
	protected static void setQueryParams(Query query,List<Object> param) {
		if(null != param && param.size() > 0) {
			for(int i=0; i<param.size(); i++) {
				query.setParameter(i,param.get(i)) ;
			}
		}
	}
	/**
	 * 设置参数值
	 * @param query
	 * @param param<Object>
	 */
	protected static void setQueryParams(Query query,Object[] param) {
		if(null != param && param.length > 0) {
			for(int i=0; i<param.length; i++) {
				query.setParameter(i,param[i]) ;
			}
		}
	}
	
	/**
	 * 组装order by语句
	 * @param orderby
	 * @return
	 */
	protected static String buildOrderBy(LinkedHashMap<String, String> orderby) {
		StringBuffer sb = new StringBuffer() ;
		
		if(null != orderby && orderby.size() > 0) {
			sb.append(BaseQuery.ORDERBY) ;
			for(String key : orderby.keySet()) {
				sb.append("o.").append(key).append(" ").append(orderby.get(key)).append(",") ;
			}
			sb.deleteCharAt(sb.length() - 1) ;
		}
		return sb.toString() ;
	}

	/**
	 * 组装查询属性
	 * @param property
	 * @return
	 */
	public static String buildProperty(String property) {
		return (null != property && !"".equals(property.trim())? property.trim() : "") ;
	}

}
